package uk.co.agileworks.bidpirate.service;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URLDecoder;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ApplicationObjectSupport;
import org.springframework.stereotype.Service;

import uk.co.agileworks.bidpirate.model.CurrencyAndPrice;
import uk.co.agileworks.bidpirate.model.Item;

import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlImage;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSpan;
import com.gargoylesoftware.htmlunit.html.HtmlStrong;

@Service
public class EbayFacadeImpl extends ApplicationObjectSupport implements EbayFacade {

	private static final Logger LOGGER = LoggerFactory.getLogger(EbayFacadeImpl.class);
	
	private static final String MOB_EBAY_TZ = "PST";

	@Resource
	private String viewItemUrl;

	@Override
	public Date getDate(String formattedDate) {

		SimpleDateFormat parser = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss a z", Locale.ROOT);
		try {
			return parser.parse(formattedDate + " " + MOB_EBAY_TZ);
		} catch (ParseException e) {
			throw new IllegalArgumentException(e);
		}
	}

	@Override
	public Long getItemNumber(String itemNumberOrUrl) {

		Pattern pattern = Pattern.compile("\\d{12}");
		Matcher matcher = pattern.matcher(itemNumberOrUrl);
		if (matcher.find()) {
			return Long.parseLong(itemNumberOrUrl.substring(matcher.start(), matcher.end()));
		} else {
			throw new ServiceException("itemNumber.invalid");
		}
	}

	@Override
	public CurrencyAndPrice getCurrencyAndPrice(String currencyAndPrice) {

		Pattern pattern = Pattern.compile("\\d");
		Matcher matcher = pattern.matcher(currencyAndPrice);
		matcher.find();

		String currency = currencyAndPrice.substring(0, matcher.start());
		String value = currencyAndPrice.substring(matcher.start());
		try {
			return new CurrencyAndPrice(currency, new DecimalFormat().parse(value).doubleValue());
		} catch (ParseException e) {
			throw new IllegalArgumentException(e);
		}
	}

	// TODO make xpath more resilient
	@Override
	public Item getItem(long itemNumber) {

		String itemNumberString = String.valueOf(itemNumber);
		String itemUrl = viewItemUrl.replaceFirst("%ITEM_NUMBER%", itemNumberString);

		WebClient webClient = new WebClient();
		webClient.setJavaScriptEnabled(false);
		try {
			HtmlPage page = webClient.getPage(itemUrl);
			String titleText = page.getTitleText();
			if ("eBay mobile".equals(titleText)) {
				throw new ServiceException("item.not.found");
			}
			HtmlStrong type = page.getFirstByXPath("/html/body/div/div[3]/div[3]/span/a/strong");
			if ("Buy It Now".equals(type.asText())) {
				throw new ServiceException("buy.it.now");
			}
			Item item = new Item(itemNumber);
			item.setDescription(StringUtils.substringBefore(titleText, " - eBay Mobile"));
			item.setEndTime(getDate(StringUtils.substringBetween(titleText, itemNumberString,
					")")));

			HtmlSpan currencyAndPrice = page
					.getFirstByXPath("/html/body/div/div[4]/div[2]/table/tbody/tr[2]/td[2]/span");
			item.setCurrencyAndPrice(getCurrencyAndPrice(currencyAndPrice.asText()));

			HtmlImage image = page
					.getFirstByXPath("/html/body/div/div[3]/div/table/tbody/tr/td/img");
			String src = StringUtils.substringAfter(image.getSrcAttribute(), "&url=");
			item.setImageUrl(URLDecoder.decode(src, "UTF-8"));

			LOGGER.info("item=[" + item + "]");
			return item;

		} catch (FailingHttpStatusCodeException e) {
			throw new IllegalStateException(e);
		} catch (MalformedURLException e) {
			throw new IllegalArgumentException(e);
		} catch (IOException e) {
			throw new IllegalStateException(e);
		}
	}

	@Override
	public EbaySession createEbaySession() {
		return getApplicationContext().getBean(EbaySession.class);
	}

}
